package com.domain.DTO;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.ObjectUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 大忽悠
 */
@AllArgsConstructor
@Data
@Builder
public class FlightInfoDto {
    private FlightDto flightDto;
    private AggregateInfo aggregateInfo;

    public FlightInfoDto() {
        aggregateInfo=new AggregateInfo();
    }

    public static FlightInfoDto wrapperFlightDto(FlightDto flightDto) {
        FlightInfoDto flightInfoDto = new FlightInfoDto();
        //如果存在多个班次,取班次中最便宜的价格进行累加
        calculateLeastPoorCost(flightInfoDto, flightDto);
        calculateLeastRichCost(flightInfoDto, flightDto);
        //如果存在多个班次,取耗时最短的班次进行累加
        calculateLeastTime(flightInfoDto,flightDto);
        flightInfoDto.setFlightDto(flightDto);
        return flightInfoDto;
    }

    private static void calculateLeastTime(FlightInfoDto flightInfoDto, FlightDto flightDto) {
        if (flightDto == null) {
            return;
        }
        flightInfoDto.addTimeCost(flightDto.getTimeCost());

        List<FlightDto> flightDtoNext = flightDto.getNext();
        if(ObjectUtils.isEmpty(flightDtoNext)){
            return;
        }

        //过滤出耗时最低的
        FlightDto leastTimeCost = flightDtoNext.stream().sorted((flightDto1, flightDto2) -> (int) (flightDto1.getTimeCost() - flightDto2.getTimeCost())).collect(Collectors.toList()).get(0);
        //递归累加
        calculateLeastTime(flightInfoDto,leastTimeCost);
    }

    private void addTimeCost(Long time) {
            getAggregateInfo().totalTime+=time;
    }

    private static void calculateLeastRichCost(FlightInfoDto flightInfoDto, FlightDto flightDto) {
        if (flightDto == null) {
            return;
        }
        flightInfoDto.addRichCost(flightDto.getRichPrice());

        List<FlightDto> flightDtoNext = flightDto.getNext();
        if(ObjectUtils.isEmpty(flightDtoNext)){
            return;
        }

        //过滤出价格最低的经济舱
        FlightDto cheapestRichPrice = flightDtoNext.stream().sorted((flightDto1, flightDto2) -> (int) (flightDto1.getPoorPrice() - flightDto2.getPoorPrice())).collect(Collectors.toList()).get(0);
        //递归累加
        calculateLeastRichCost(flightInfoDto,cheapestRichPrice);
    }


    private static void calculateLeastPoorCost(FlightInfoDto flightInfoDto, FlightDto flightDto) {
        if (flightDto == null) {
            return;
        }
        flightInfoDto.addPoorCost(flightDto.getPoorPrice());

        List<FlightDto> flightDtoNext = flightDto.getNext();
        if(ObjectUtils.isEmpty(flightDtoNext)){
            return;
        }

        //过滤出价格最低的经济舱
        FlightDto cheapestPoorPrice = flightDtoNext.stream().sorted((flightDto1, flightDto2) -> (int) (flightDto1.getPoorPrice() - flightDto2.getPoorPrice())).collect(Collectors.toList()).get(0);
        //递归累加
        calculateLeastPoorCost(flightInfoDto,cheapestPoorPrice);
    }

    private void addRichCost(Double richPrice) {
         getAggregateInfo().totalRichPrice+=richPrice;
    }


    private void addPoorCost(Double poorPrice) {
         getAggregateInfo().totalPoorPrice+=poorPrice;
    }


    public void filterBestFlightClassByTimeStrategy() {
         doFilterBestFlightClassByTimeStrategy(flightDto);
    }

    private void doFilterBestFlightClassByTimeStrategy(FlightDto flightDto) {
        List<FlightDto> flightDtoNextList = flightDto.getNext();
        if(ObjectUtils.isEmpty(flightDtoNextList)){
            return;
        }
        FlightDto bestCostFlightClass = flightDtoNextList.stream().sorted((fd1, fd2) -> (int) (fd1.getTimeCost() - fd2.getTimeCost())).collect(Collectors.toList()).get(0);
        flightDto.setNext(List.of(bestCostFlightClass));
        doFilterBestFlightClassByTimeStrategy(bestCostFlightClass);
    }

    public void filterBestFlightClassByMoneyStrategy() {
        doFilterBestFlightClassByMoneyStrategy(flightDto);
    }

    private void doFilterBestFlightClassByMoneyStrategy(FlightDto flightDto) {
        List<FlightDto> flightDtoNextList = flightDto.getNext();
        if(ObjectUtils.isEmpty(flightDtoNextList)){
            return;
        }
        FlightDto bestCostFlightClass = flightDtoNextList.stream().sorted((fd1, fd2) -> (int) (fd1.getPoorPrice() - fd2.getPoorPrice())).collect(Collectors.toList()).get(0);
        flightDto.setNext(List.of(bestCostFlightClass));
        doFilterBestFlightClassByMoneyStrategy(bestCostFlightClass);
    }


    /**
     * 本条航线信息汇总
     */
    @AllArgsConstructor
    @NoArgsConstructor
    @Data
    @Builder
    public static class AggregateInfo {
        /**
         * 本路径全部选择经济舱总费用--最低
         */
        private Double totalPoorPrice = 0d;
        /**
         * 本路径全部选择商务舱总费用--最低
         */
        private Double totalRichPrice = 0d;
        /**
         * 本路径选择总耗时: 单位为分钟--最少
         */
        private Long totalTime = 0L;
    }
}
